/*
 * ShUIE 1.0.0 - SharePoint User-Interface Extender
 *
 * Copyright (c) 2005-2008 David Kitchen (pcubed.com) and
 * Copyright (c) 2005-2008 Louise Brighton (pcubed.com)
 * 
 * Licensed under the CDDL (LICENSE.txt)
 */
using System;
using System.Collections;
using System.Globalization;
using System.Threading;
using System.Web.UI;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

//
// Taken from: http://code.google.com/p/jsonexserializer/
// Built on 2008-12-05
// See JsonExSerializer.license.txt included with this source code for license details.
//
using JsonExSerializer;

//
// Taken from: http://www.codeplex.com/YUICompressor
// Built on 2008-11-12
// See YUICompressor.license.txt included with this source code for license details.
//
using Yahoo.Yui.Compressor;

using PcubedContext = Pcubed.Shuie.ContextProvider;

namespace Pcubed.Shuie
{
  public class AjaxInjector : SPControl
  {
    protected override void Render(HtmlTextWriter output)
    {
      try
      {
        // adding JavaScript references to jQuery
        outputJsLinkToSource(
          output,
          ResolveUrl("~/_wpresources/Pcubed.ShUIE/1.0.0.0__e10d7838767586ca/jquery.js")
          );
        outputJsLinkToSource(
          output,
          ResolveUrl("~/_wpresources/Pcubed.ShUIE/1.0.0.0__e10d7838767586ca/jquery.ui.js")
          );
        outputJsLinkToSource(
          output,
          ResolveUrl("~/_wpresources/Pcubed.ShUIE/1.0.0.0__e10d7838767586ca/raphael.js")
          );

        SPSite siteCollection = GetContextSite(Context);
        SPWeb siteCollectionWeb = siteCollection.RootWeb;

        output.WriteLine(String.Format("<!-- Site Collection URL: {0} -->", siteCollectionWeb.Url));

        if (siteCollectionWeb.Properties.Count > 0)
        {
          PcubedContext.ContextProvider context = PcubedContext.ContextProvider.GetContext();
          Serializer serializer = new Serializer(typeof(PcubedContext.ContextProvider));

          outputJs(
            output,
            MinifyJs(
              String.Format(
                "var p3context = {0};",
                serializer.Serialize(context).Replace(":(int)", ":").Replace(":(System.DateTime)", ":")
              )
            )
          );

          Guid lastInjectId = Guid.Empty;
          String userLogin = String.Empty;
          String userName = String.Empty;
          Boolean userIsSiteAdmin = false;
          Boolean userIsWebAdmin = false;

          try
          {
            userLogin = SPContext.Current.Web.CurrentUser.LoginName;
            userName = SPContext.Current.Web.CurrentUser.Name;
            userIsSiteAdmin = SPContext.Current.Web.UserIsSiteAdmin;
            userIsWebAdmin = SPContext.Current.Web.UserIsWebAdmin;
          }
          catch (Exception ex)
          {
            output.WriteLine(String.Format("<!--{0}-->", ex.Message));
          }
          PcubedContext.ShuieContext shuieContext = context.GetShuieContext();
          shuieContext.UserLogin = userLogin;
          shuieContext.UserName = userName;
          shuieContext.UserIsSiteAdmin = userIsSiteAdmin;
          shuieContext.UserIsWebAdmin = userIsWebAdmin;

          SortedList entriesToRender = new SortedList();
          foreach (String key in siteCollectionWeb.Properties.Keys)
          {
            if (!key.StartsWith("shuie_"))
              continue;

            ShuieXml shuieXml = new ShuieXml();
            shuieXml.LoadXml(siteCollectionWeb.Properties[key]);

            if (!(shuieXml.IsActive && shuieXml.CheckContext(shuieContext)))
              continue;

            Guid curInjectId = shuieXml.Id;
            if (curInjectId.Equals(lastInjectId) || curInjectId.Equals(Guid.Empty))
              continue;

            lastInjectId = curInjectId;

            Int32 order = shuieXml.Order;
            while (entriesToRender.ContainsKey(order))
              order++;

            entriesToRender.Add(order, shuieXml);
          }

          foreach (Object obj in entriesToRender.Values)
          {
            ShuieXml shuieXml = (ShuieXml)obj;
            String javaScript = shuieXml.GetJavaScriptOutput();

            if (!javaScript.Equals(String.Empty))
              outputJs(output, javaScript, shuieXml.Title, "javascript");

            String[] mediaTypes = shuieXml.GetMediaTypes();
            for (Int32 ii = 0; ii < mediaTypes.Length; ii++)
            {
              String css = shuieXml.GetCssOutput(mediaTypes[ii]);
              if (!css.Equals(String.Empty))
                outputCss(output, css, mediaTypes[ii], shuieXml.Title);
            }

            String json = shuieXml.GetJsonOutput();
            if (!json.Equals(String.Empty))
              outputJs(output, json, shuieXml.Title, "json");
          }
        }
      }
      catch (Exception exc)
      {
        output.WriteLine("<!--");
        output.WriteLine("Exception occured whilst rendering ShUIE scripts.");
        output.WriteLine("ShUIE has been disabled to prevent breaking the page.");
        output.WriteLine("Please examine the following information to determine the root cause:");
        output.WriteLine(exc.Message);
        output.WriteLine(exc.Source);
        output.WriteLine(exc.StackTrace);

        if (null != exc.InnerException)
        {
          output.WriteLine(exc.InnerException.Source);
          output.WriteLine(exc.InnerException.StackTrace);
        }
        output.WriteLine("-->");
      }
      try
      {
        // Explicitly setting the LCID for the Credit Suisse bug
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
      }
      catch (Exception exc)
      {
        output.WriteLine("<!--");
        output.WriteLine("This is a warning only, an exception occured whilst trying to change the UI LCID to en-US.");
        output.WriteLine("As we can't change it, we are continuing with the default LCID that SharePoint figured out somehow.");
        output.WriteLine("-->");
      }
    }

    static void outputJs(HtmlTextWriter output, String js)
    {
      output.WriteLine(
        String.Format("<script type=\"text/javascript\" language=\"javascript\">{0}</script>", js)
        );
    }

    static void outputJs(HtmlTextWriter output, String js, String title, String scriptType)
    {
      output.WriteLine(String.Format("<!-- START of ShUIE {0}: {1} -->", scriptType.ToUpperInvariant(), title));

      output.WriteLine(
        String.Format("<script type=\"text/javascript\" language=\"javascript\">{0}</script>", js)
        );

      output.WriteLine(String.Format("<!-- END of ShUIE script: {0}: {1} -->", scriptType.ToUpperInvariant(), title));
    }

    static void outputJsLinkToSource(HtmlTextWriter output, String js)
    {
      output.WriteLine(
        String.Format("<script type=\"text/javascript\" language=\"javascript\" src=\"{0}\"></script>", js)
        );
    }

    static void outputCss(HtmlTextWriter output, String css, String cssMediaType, String title)
    {
      output.WriteLine(String.Format("<!-- START of ShUIE CSS: {0} -->", title));

      output.WriteLine(
        String.Format("<style type=\"text/css\" media=\"{0}\">{1}</style>", cssMediaType, css)
        );

      output.WriteLine(String.Format("<!-- END of ShUIE CSS: {0} -->", title));
    }

    static String MinifyJs(String js)
    {
      return JavaScriptCompressor.Compress(js);
    }
  }
}